package com.wiscamp.ninechapters.challenges.domain.repositories;

import com.wiscamp.ninechapters.challenges.domain.models.GroupUser;
import com.wiscamp.ninechapters.challenges.domain.models.InviteHelp;
import com.wiscamp.ninechapters.challenges.domain.models.UserGroup;
import com.wiscamp.ninechapters.challenges.infrastructure.mappers.ChallengeGroupUserMapper;
import com.wiscamp.ninechapters.challenges.infrastructure.mappers.ChallengeUserGroupMapper;
import com.wiscamp.ninechapters.challenges.infrastructure.mappers.InviteHelpMapper;
import com.wiscamp.ninechapters.challenges.infrastructure.po.GroupUserPO;
import com.wiscamp.ninechapters.challenges.infrastructure.po.InviteHelpPO;
import com.wiscamp.ninechapters.challenges.infrastructure.po.UserGroupPO;
import cube.ddd.aspect.AopDataException;
import com.wiscamp.ninechapters.common.core.CollectionHelper;
import jakarta.validation.constraints.NotNull;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest;
import org.springframework.stereotype.Repository;

import java.util.Collection;
import java.util.Objects;

@Repository
public class GroupsRepository {
    @Autowired
    private ChallengeUserGroupMapper userGroupMapper;

    @Autowired
    private ChallengeGroupUserMapper groupUserMapper;

    @Autowired
    private InviteHelpMapper inviteHelpMapper;

    //region converter
    public UserGroup toUserGroup(@NotNull UserGroupPO po) {
        var entity = new UserGroup();
        BeanUtils.copyProperties(po, entity);
        return entity;
    }

    public UserGroupPO toUserGroupPO(@NotNull UserGroup entity) {
        var po = new UserGroupPO();
        BeanUtils.copyProperties(entity, po);
        return po;
    }

    public GroupUser toGroupUser(@NotNull GroupUserPO po) {
        var entity = new GroupUser();
        BeanUtils.copyProperties(po, entity);
        return entity;
    }

    public GroupUserPO toGroupUserPO(@NotNull GroupUser entity) {
        var po = new GroupUserPO();
        BeanUtils.copyProperties(entity, po);
        return po;
    }

    public InviteHelp toInviteHelp(@NotNull InviteHelpPO po) {
        var entity = new InviteHelp();
        BeanUtils.copyProperties(po, entity);
        return entity;
    }

    public InviteHelpPO toInviteHelpPO(@NotNull InviteHelp entity) {
        var po = new InviteHelpPO();
        BeanUtils.copyProperties(entity, po);
        return po;
    }
    //endregion


    @AopDataException
    public UserGroup saveUserGroup(UserGroup userGroup) {
        var userGroupPO = toUserGroupPO(userGroup);
        var savedPO = userGroupMapper.saveAndFlush(userGroupPO);
        if (Objects.nonNull(savedPO))
            return toUserGroup(savedPO);
        return null;
    }

    @AopDataException
    public void saveUserGroups(Collection<UserGroup> userGroups) {
        Collection<UserGroupPO> groupPOList = CollectionHelper.convertToArrayList(userGroups, this::toUserGroupPO);
        userGroupMapper.saveAll(groupPOList);
    }

    @AopDataException
    public GroupUser saveGroupUser(GroupUser groupUser) {
        var groupUserPO = toGroupUserPO(groupUser);
        var savedPO = groupUserMapper.saveAndFlush(groupUserPO);
        if (Objects.nonNull(savedPO))
            return toGroupUser(savedPO);
        return null;
    }

    @AopDataException
    public UserGroup getUserGroupById(long groupId) {
        var optionalGroupPO = userGroupMapper.findById(groupId);
        if (optionalGroupPO.isPresent())
            return toUserGroup(optionalGroupPO.get());
        return null;
    }

    @AopDataException
    public UserGroup getUserGroupByManager(long managerId) {
        var userGroupPO = userGroupMapper.getByManagerId(managerId);
        if (Objects.nonNull(userGroupPO))
            return toUserGroup(userGroupPO);
        return null;
    }

    @AopDataException
    public Collection<UserGroup> findTop100OrderByTotalPoints(PageRequest pageable) {
        var groups = userGroupMapper.findTop100OrderByTotalPoints(pageable);
        return CollectionHelper.convertToArrayList(groups.getContent(), this::toUserGroup);
    }

    @AopDataException
    public void rankingAfter100ByPoints(Collection<Long> groupIds) {
        userGroupMapper.rankingAfter100ByPoints(groupIds);
    }

    @AopDataException
    public GroupUser findFirstMemberByUserId(long userId) {
        var groupUserPO = groupUserMapper.findFirstByUserId(userId);
        if (Objects.nonNull(groupUserPO))
            return toGroupUser(groupUserPO);

        return null;
    }

    @AopDataException
    public Collection<GroupUser> getGroupUsers(long groupId) {
        var groupUserPOList = groupUserMapper.getGroupUsers(groupId);
        return CollectionHelper.convertToArrayList(groupUserPOList, this::toGroupUser);
    }

    @AopDataException
    public InviteHelp getInviteHelp(long userId, int year, int month, int day, long supporterId) {
        var inviteHelpPO = inviteHelpMapper.getInviteHelp(userId, year, month, day, supporterId);
        if (Objects.nonNull(inviteHelpPO))
            return toInviteHelp(inviteHelpPO);
        return null;
    }

    @AopDataException
    public Collection<InviteHelp> getInviteHelps(long userId, int year, int month, int day) {
        var inviteHelpPOList = inviteHelpMapper.getInviteHelps(userId, year, month, day);
        return CollectionHelper.convertToArrayList(inviteHelpPOList, this::toInviteHelp);
    }

    @AopDataException
    public InviteHelp saveInviteHelp(InviteHelp inviteHelp) {
        var inviteHelpPO = toInviteHelpPO(inviteHelp);
        var savedPO = inviteHelpMapper.saveAndFlush(inviteHelpPO);
        if (Objects.nonNull(savedPO))
            return toInviteHelp(savedPO);
        return null;
    }
}
